// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 此文件为平台实现accept，为
// 设置SetNonblock和CloseOnExec提供快速路径。

// go:build dragonfly | | freebsd | | illumos | | linux | | netbsd | | openbsd 

package poll

import "syscall"

// accept系统调用的包装器，该调用将返回的文件
// 描述符标记为非阻塞，并在exec上关闭。
func accept(s int) (int, syscall.Sockaddr, string, error) {
	ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
	// 在Linux上，accept4系统调用是在2.6.28内核中引入的，在FreeBSD上，它是在10内核中引入的。如果我们在Linux和FreeBSD上都出现ENOSYS错误，或者在Linux上出现EINVAL 
	// 错误，请使用accept。
	switch err {
	case nil:
		return ns, sa, "", nil
	default: // 除了列出的错误之外的错误
		return -1, sa, "accept4", err
	case syscall.ENOSYS: // 系统调用缺少
	case syscall.EINVAL: // 一些Linux使用它代替ENOSYS 
	case syscall.EACCES: // 一些Linux使用它代替ENOSYS 
	case syscall.EFAULT: // 一些Linux使用它代替ENOSYS 
	}

	// 参见/syscall/exec_unix。请查阅ForkLock的描述。
	// 在syscall中保持锁可能是可以的。接受
	// 因为我们已经把fd。sysfd进入非阻塞模式。
	// 但是，对File方法的调用将使其返回到
	// 阻塞模式。我们不能冒这个险，所以这里不用叉子锁。
	ns, sa, err = AcceptFunc(s)
	if err == nil {
		syscall.CloseOnExec(ns)
	}
	if err != nil {
		return -1, nil, "accept", err
	}
	if err = syscall.SetNonblock(ns, true); err != nil {
		CloseFunc(ns)
		return -1, nil, "setnonblock", err
	}
	return ns, sa, "", nil
}
